require "Battle/Manager/SpineEffectManager"
require 'Battle/Entity/SpineEffectParam'
require 'Battle/Entity/ParticleSystemEffect'
require 'Battle/Entity/ParticleSystemEffectParam'
require "Battle/Entity/EffectFunctions"
--- @class SpineEffect

SpineEffect = {}
local SpineEffect = SpineEffect
local mt = { __index = SpineEffect }

local cacheList = {}
function SpineEffect.Get(param)
    local eff = table.remove(cacheList, 1);
    if eff then
        eff:InitData(param)
        return eff;
    end

    return SpineEffect:newV2(param);
end

function SpineEffect.Put(spineEff)
    if not spineEff then
        return ;
    end
    if spineEff.effGo then
        print("self.effGo")
        return ;
    end

    spineEff.skillId = 0;
    spineEff.name = nil;
    spineEff.subName = nil
    -- spineEff.subName = string.split(spineEff.name,"/"); -- 看了下这里不需要切割了，后期有问题再改回来
    spineEff.actionName = nil;

    spineEff.depth = nil;
    spineEff.pos = nil;
    spineEff.offset = nil;
    spineEff.duration = nil;

    spineEff.flip = nil;
    spineEff.speed = nil;
    spineEff.loop = nil;

    spineEff.follow = nil;
    spineEff.followInfo = nil;

    spineEff.linkEffect = nil;
    spineEff.followInfo1 = nil;

    spineEff.flyHold = nil;

    spineEff.delay = nil;
    --spineEff.isShadow = param.isShadow;
    --spineEff.buffServerId = param.buffServerId;
    spineEff.fighterId = nil;

    spineEff.scale = nil;
    spineEff.timeScale = nil;

    --internal vars
    spineEff.renderOrder = nil;
    spineEff.psEffect = nil;

    spineEff.hook = nil;
    spineEff.tempV3:Set(0, 0, 0)
    spineEff.caster = nil;
    spineEff.suffer = nil;
    spineEff.spineType = 0;
    spineEff.isCut = nil;
    spineEff.targetPos = nil;

    --使用对象池fxh003o技能，缇娜的必杀技，放到一半消失，此技能应该是在缇娜的skillEffect里，但是断点显示在其他人的skillEffect里。使用对象池，引用关系没有处理干净。
    --table.insert(cacheList, spineEff);
    --printError("#cacheList", #cacheList)
end

function SpineEffect:newV2(param)
    local object = {};
    object.cacheVec = Vector3.New(0, 0, 0)
    SpineEffect.InitData(object, param)
    setmetatable(object, mt);
    return object;
end

function SpineEffect:InitData(param)
    --object.effectRes = param.effectRes;
    self.skillId = param.skillId;
    self.name = param.effectRes;
    self.subName = self.name
    -- self.subName = string.split(self.name,"/"); -- 看了下这里不需要切割了，后期有问题再改回来
    self.actionName = param.actionName;
    self.skillShowType = param.skillShowType or 0
    self.depth = param.depth;
    if param.pos then
        self.pos = param.pos:Clone();
    else
        self.pos = nil;
    end
    self.offset = param.offset;
    self.duration = param.duration;

    self.flip = param.flip;

    if param.speed then
        self.speed = param.speed;
    else
        self.speed = nil;
    end

    self.loop = param.loop;

    self.follow = param.follow;
    self.followInfo = param.followInfo;

    self.linkEffect = param.linkEffect;
    self.followInfo1 = param.followInfo1;

    self.flyHold = param.flyHold;

    self.delay = param.delay;
    self.delayCallId = nil;
    --self.isShadow = param.isShadow;
    --self.buffServerId = param.buffServerId;
    self.fighterId = param.fighterId;

    self.scale = param.scale or 1;
    self.timeScale = param.timeScale;

    --internal vars
    self.renderOrder = -100;
    self.psEffect = nil;

    self.hook = param.hook;
    self.tempV3 = self.cacheVec;
    self.tempV3:Set(0, 0, 0)
    self.caster = param.caster;
    self.suffer = param.suffer;
    self.f_AxisDeviation = tonumber(param.f_AxisDeviation) or 0
    self.RenderQueueRate = (self.skillId / 100000000000 + 0.12 + self.f_AxisDeviation) * -1
    self.func = nil
    self.spineType = param.spineType;
    self.targetPos = param.targetPos;

    local skillShow = G.dataTable["t_skillshow"][tostring(self.skillId)];
    if skillShow then
        self.isCut = skillShow["f_Interrupt"];--为1则技能可以被新技能打断 否则不行
    else
        self.isCut = nil;
    end
    SpineEffectParam.Put(param);
end

function SpineEffect:init()
    self.ending = false;

    if not self.rotatedOffset then
        self.rotatedOffset = Vector3(0, 0, 0)
    end
    local flip = self.flip;
    if self.caster and self.caster.partnerModelId == "611" then
        self.flip = self.caster.flip;
    end
    self.rotatedOffset = EffectFunctions.rotateOffset(self.offset, self.flip, self.rotatedOffset);

    if self.followInfo and self.followInfo.offset then
        if not self.followInfo.rotatedOffset then
            self.followInfo.rotatedOffset = Vector3(0, 0, 0)
        end
        self.followInfo.rotatedOffset = EffectFunctions.rotateOffset(self.followInfo.offset, self.flip, self.followInfo.rotatedOffset);
    end

    if self.followInfo1 and self.followInfo1.offset then
        if not self.followInfo1.rotatedOffset then
            self.followInfo1.rotatedOffset = Vector3(0, 0, 0)
        end
        self.followInfo1.rotatedOffset = EffectFunctions.rotateOffset(self.followInfo1.offset, self.flip, self.followInfo1.rotatedOffset);
    end

end

--function SpineEffect.rotateOffset(offset, flip)
--    local offsetPos = offset;
--    local offsetY = Mathf.Cos(Mathf.PI/6) * offsetPos[2];
--    local offsetZ = Mathf.Sin(Mathf.PI/6) * offsetPos[2];
--    local offsetX = tonumber(offsetPos[1]);
--    if flip then
--        offsetX = -offsetX;
--    end
--
--    return Vector3(offsetX, offsetY, offsetZ);
--end

--function SpineEffect:setMoveSpeed(speed)
--	self.speed = speed;
--end
--
--function SpineEffect:setFollow(follow,parent)
--    self.follow = follow;
--    self.followTrans = parent;
--end
--
--function SpineEffect:setFlyHold(hold)
--    self.flyHold = hold;
--end

function SpineEffect:setFunc(func)
    self.func = func;
end

function SpineEffect:startDelay()
    --logError('starDelay delay = '..delay .. ' actionName = ' .. actionName);
    if self.delay > 0.01 then
        -- > 0
        self.delayCallId = utimer.delayCall(function()
            self.delayCallId = nil;
            self:start();
        end, self.delay * 1000)
    else
        --logError('start imm.')
        self:start();--actionName
    end
end

--function SpineEffect:getAsset(isShadow, resName)
--    local effGo = nil;
--    local skeletonDataPath = nil;
--    local materialPath = nil;
--    local effectGoName = nil;
--
--    if isShadow then
--        skeletonDataPath = resName .. "/skeleton_shadow_SkeletonData";
--        materialPath = resName .. "/skeleton_shadow_Material";
--        effectGoName = 'spineShadow';
--    else
--        local subName = string.split(resName,"/");
--        effGo =  SpineEffectManager.getEffect(subName[#subName]);
--
--        if effGo == nil then
--            local effectCfg = G.dataTable["t_effect"][tostring(resName)];
--            if effectCfg ~= nil then
--                local tmp = Entity:GetTableValue(effectCfg,"f_ModelName");
--                skeletonDataPath = tmp.."_SkeletonData";
--                materialPath = tmp .. "_Material";
--                effectGoName = resName;
--            end
--        end
--    end
--
--    return effGo, skeletonDataPath, materialPath, effectGoName;
--end

--暂定， actionName为nil的是shadow, role shadow 不加入pool
function SpineEffect:start()
    --actionName
    --logError("SpineEffect:start: "..actionName .. ' ending = ' .. tostring(self.ending));

    --if string.find(self.name,'b017') ~= nil then
    --    logMy('SpineEffect:start1', self.name, self.duration, self.actionName);
    --end

    --如果在starDelay的过程中，由于buff结束已经被删掉了
    if self.ending then
        return ;
    end

    if not self.handle then
        self.handle = UpdateBeat:Add(self.update, self);
        --self.handle = LateUpdateBeat:Add(self.update, self);
    end

    local effGo = nil;

    if self.isCut == 1 and self.spineType == EnumConst.SpineEffectType.SKILL then
        --需要打断的动画
        effGo = SpineEffectManager.getPlayingEffect(self.caster.fighterId, self.subName);
    end
    if effGo == nil then
        effGo = SpineEffectManager.getEffect(self.subName);
    end
    --静态脚本没有填特效全路径
    --local i,j = string.find(self.name,"/");
    local effName = self.name;
    --self.ending = false;
    self.loaded = false;

    --local effGo, skeletonDataPath, materialPath, effectGoName = SpineEffect:getAsset(self.isShadow, self.name);

    if effGo == nil then
        resMgr:LoadModelPrefab("Prefabs/Skill/" .. effName, function(obj1)

            --如果在异步载入的过程中，由于buff结束已经被删掉了
            if self.ending then
                return ;
            end

            local skillObj = newObject(obj1);
            --skillObj.transform.name = effName;
            --skillObj.transform.name = effectGoName;
            self.effGo = skillObj;
            if panelMgr.BattleRound and panelMgr.BattleRound.gameObject.activeInHierarchy == true then
                self.effGo.transform:SetParent(panelMgr.BattleRound);
                self.scale = self.scale * FightManager.getScaleParam(panelMgr.BattleRound);
            elseif panelMgr.BattleMain and panelMgr.BattleMain.gameObject.activeInHierarchy == true then
                self.effGo.transform:SetParent(panelMgr.BattleMain);
                self.scale = self.scale * FightManager.getScaleParam(panelMgr.BattleMain);
            end
            Util.Lua_SetLocalScaleXYZ(self.effGo, self.scale, self.scale, self.scale);
            Util.Lua_SetLocalRotationXYZ(self.effGo, 40, 0, 0);
            self:initOther();
            self:initPosition();
            self.loaded = true;
            if not self.hook then
                self:playAction(self.actionName);
            end
        end);
    else
        self.effGo = effGo;
        if panelMgr.BattleRound and panelMgr.BattleRound.gameObject.activeInHierarchy == true then
            self.effGo.transform:SetParent(panelMgr.BattleRound);
            self.scale = self.scale * FightManager.getScaleParam(panelMgr.BattleRound);
        elseif panelMgr.BattleMain and panelMgr.BattleMain.gameObject.activeInHierarchy == true then
            self.effGo.transform:SetParent(panelMgr.BattleMain);
            self.scale = self.scale * FightManager.getScaleParam(panelMgr.BattleMain);
        end
        Util.Lua_SetLocalScaleXYZ(self.effGo, self.scale, self.scale, self.scale);
        Util.Lua_SetLocalPositionXYZ(self.effGo, 0, 0, 0);
        Util.Lua_SetLocalRotationXYZ(self.effGo, 40, 0, 0);

        self:initOther();
        self:initPosition();
        self.loaded = true;

        if not self.hook then
            self:playAction(self.actionName);
        end
    end

    --if self.hook and self.lbone and self.rbone then
    --    --EffectFunctions.calcFollowPositionV2(self.followInfo);
    --    --self.lbone.position = self.followInfo.position;
    --    --self.rbone.position = self.followInfo.position;
    --    self.tempV3 = self.followInfo.position;
    --    printError("self.rbone.position", self.rbone.position.x)
    --end

end

function SpineEffect:bindLinkEffect(skeletonAnimation, is)
    if is or self.linkEffect or self.hook then
        --skeletonAnimation: Spine.Unity.SkeletonAnimation
        self.skeletonAnimationTrans = skeletonAnimation.transform;
        --self.lbone = skeletonAnimation.Skeleton:FindBone("l");
        --self.rbone = skeletonAnimation.Skeleton:FindBone("r");

        --transform
        self.lbone = Util.GetSpineBoneAsTransform(self.skeletonAnimation, 'l', 1);
        self.rbone = Util.GetSpineBoneAsTransform(self.skeletonAnimation, 'r', 1);

    end
end

--function SpineEffect:updateLinkEffect_()
--    if self.linkEffect and self.lbone and self.rbone then
--        --self.lbone.position = self.l.position
--        --self.rbone.position = self.r.position
--
--        local lw = self.l.position;
--        local rw = self.r.position;
--        lw.y = lw.y + self.linkEffectOffset;
--        rw.y = rw.y + self.linkEffectOffset;
--
--
--
--        self.lbone.position = lw;
--        self.rbone.position = rw;
--
--        self.effGo.transform.position = Vector3((lw.x + rw.x)/2, (lw.y + rw.y)/2, (lw.z + rw.z)/2);
--
--    end
--end

local CacheRight = Vector3.right;
local CacheNormalVec3 = Vector3.New(0, 0, 0)

function SpineEffect:updateLinkEffect()
    --if self.name == 'b012' then
    --    logMy('updateLinkEffect', self.linkEffect, self.lbone == nil, self.rbone == nil, self.followInfo, self.followInfo1);
    --end

    if self.linkEffect and self.lbone and self.rbone then
        if self.caster and self.caster:getDeadState() or self.suffer and self.suffer:getDeadState() then
            self:stop();
            return ;
        end
        if FightManager.gameEnd then
            self:stop();
            return ;
        end
        EffectFunctions.calcFollowPositionV2(self.followInfo);
        EffectFunctions.calcFollowPositionV2(self.followInfo1);
        local lw = self.followInfo.position;
        local rw = self.followInfo1.position;
        self.lbone.position = lw;
        self.rbone.position = rw;
        local pl = (self.lbone.position.y - self.rbone.position.y) / (self.lbone.position.x - self.rbone.position.x)
        Util.Lua_SetLocalRotationXYZ(self.skeletonAnimation.gameObject, 0, 0, math.atan(pl) * 180 / math.pi);
        Util.Lua_SetGameObjectPositionXYZ(self.effGo, (lw.x + rw.x) / 2, (lw.y + rw.y) / 2, (lw.z + rw.z) / 2)
    end
end

function SpineEffect:updateHookEffect()
    --if self.name == 'b012' then
    --    logMy('updateLinkEffect', self.linkEffect, self.lbone == nil, self.rbone == nil, self.followInfo, self.followInfo1);
    --end

    if self.hook and self.lbone and self.rbone then
        if FightManager.gameEnd then
            self:stop();
            return ;
        end
        local followPos = self.followInfo.position;
        if followPos then
            Util.Lua_SetGameObjectPositionXYZ(self.effGo, followPos.x, followPos.y, followPos.z)
        end
        --    EffectFunctions.calcFollowPositionV2(self.followInfo);
        --    local lw = self.followInfo.position;
        --    local normalize = Vec3Sub(self.followInfo1.followTrans.position, self.tempV3, CacheNormalVec3);
        --    local lerp = Vec3Mul(normalize, 10 * Time.deltaTime, CacheNormalVec3);
        --    --printError("差值==", lerp.x, lerp.y, lerp.z)
        --    --printError(self.followInfo1.followTrans.name, self.followInfo1.followTrans.position.x, self.rbone.transform.parent.name, self.rbone.position.x);
        --    Vec3Add(lerp, self.tempV3, self.tempV3);
        --    local rw = self.tempV3;
        --
        --    --local rw = Vector3.Lerp(self.rbone.position, self.followInfo1.followTrans.position, 1 * Time.deltaTime);
        --    --printError("未赋值======", self.rbone.position.x);
        --    self.lbone.position = lw;
        --    self.rbone.position = rw;
        --    --printError("进来了======", self.rbone.position.x,  rw.x, self.followInfo1.followTrans.position.x);
        --
        --    --rotate
        --    local dir = Vec3Sub(self.followInfo1.followTrans.position, lw, CacheNormalVec3);
        --    dir.z = 0;
        --    local angle = Vector3.Angle(CacheRight, dir);
        --    Util.Lua_SetGameObjectRotationXYZ(self.skeletonAnimation.gameObject, 40, 0, angle);
        --    Util.Lua_SetGameObjectPositionXYZ(self.effGo, (lw.x + rw.x)/2, (lw.y + rw.y)/2, (lw.z + rw.z)/2)
    end
end

function SpineEffect:stop(dofunc, isUseSkillOut, isclear)
    --dofunc = dofunc or true
    --logMy("=======stop",self.name,self.func==nil)
    -- 不要重入
    local isSkillOut = false;
    if isUseSkillOut then
        isSkillOut = logicMgr.SkillManager.checkIsOut(self.skillId);--是否是分离技能
    end
    if self.ending then
        return ;
    end
    if isSkillOut then
        if dofunc and self.func then
            local res, str = pcall(self.func(), nil);
            if res then
                logMy("=======SpineEffect.stop Error", self.name, self.func == nil, str)
            end
            self:setFunc(nil)
        end
        table.insert(FightManager.effectTempCacheList, self);
        return ;
    end

    self.ending = true
    if self.handle then
        UpdateBeat:Remove(self.update, self);
        self.handle = nil;
    end
    if self.delayCallId then
        utimer.remove(self.delayCallId)
        self.delayCallId = nil;
    end
    if dofunc and self.func then
        local res, str = pcall(self.func(), nil);
        if res then
            logMy("=======SpineEffect.stop Error", self.name, self.func == nil, str)
        end
        self:setFunc(nil)
    end
    if self.func and not dofunc then
        --logMy("=======stop",self.name,self.skillId,"func 未被调用")
        self:setFunc(nil)
    end

    self.speed = nil;

    if self.effGo ~= nil then
        --if self.isShadow then
        --    destroy(self.effGo);
        --else
        local fighterId = nil;
        if self.caster ~= nil then
            fighterId = self.caster.fighterId
        end
        if isclear then
            destroy(self.effGo)
        else
            SpineEffectManager.releaseEffect(self.effGo, self.name, fighterId, self.isCut)
        end
        --end

        self.effGo = nil;
    end

    if self.psEffect then
        self.psEffect:stopDelay();
        self.psEffect = nil;
    end

    --if self.name == 'fullscreen' then
    --    logMy('stop effect',  self.name, Time.time, self.duration);
    --end

    --if self.effGo then
    --    if string.Contains( self.effGo.gameObject.name, "fxh003o") then
    --        printError(111)
    --    end
    --end
    SpineEffect.Put(self);
end

function SpineEffect:pause()
    if self.subName == nil then
        return
    end
    self.pauseState = true;
    --Util.PauseCurrentAction(self.effGo.transform:Find("Animation").gameObject);
    if not HelperFunc.IsNull(self.skeletonAnimation) then
        Util.PauseCurrentAction(self.skeletonAnimation.gameObject);
    end

    if self.psEffect then
        self.psEffect:pause();
    end
end

function SpineEffect:play()
    if self.subName == nil then
        return
    end
    self.pauseState = false;
    --Util.ResumeCurrentAction(self.effGo.transform:Find("Animation").gameObject);

    if not HelperFunc.IsNull(self.skeletonAnimation) and not HelperFunc.IsNull(self.skeletonAnimation.gameObject) and self.timeScale then
        --printError("ResumeCurrentAction======id, skillid", self.fighterId, self.skillId, self.name, self.timeScale)
        Util.ResumeCurrentAction(self.skeletonAnimation.gameObject, self.timeScale);
    end

    if self.psEffect then
        self.psEffect:play();
    end
end

function SpineEffect:update()
    if self.ending or self.effGo == nil or (not self.loaded) or (FightManager.cutInStalte and self.fighterId ~= FightManager.cutInFighterId) then
        --if string:find(self.name,'fxh002f') ~= nil and self.duration == nil then
        --    logMy('SpineEffect:update', self.name, self.duration);
        --end
        return
    end
    if self.subName == "fxh068f" and self.actionName == "skill3" then
        local a = 1;
    end
    if self.pauseState ~= nil and self.pauseState then
        return ;
    end

    self:updateRenderOrder();

    if self.duration == nil then
        return ;
    end

    if self.caster and self.caster.isMask and self.spineType ~= EnumConst.SpineEffectType.BUFF then
        local skillInfo = G.dataTable["t_skill"][tostring(self.skillId)]
        local attackIsPos = false;
        if skillInfo then
            attackIsPos = tonumber(skillInfo.f_AreaTarget) == 7 or tonumber(skillInfo.f_AreaTarget) == 8;
        end
        if not attackIsPos then
            self:stop()
            return
        end
    end
    if self.caster and self.caster.isMask and self.spineType == EnumConst.SpineEffectType.BUFF then
        local is = true;
        if self.skillId >= 225100 and self.skillId <= 225500 then
            if self.skillId % 10 == 1 then
                --变鸡不隐藏
                is = false;
            end
        end
        if is then
            self:stop()
            return
        end
    end
    if self.caster and FightManager.fightType == EnumConst.FightTypeConst.PerformBattle and self.caster.curFadeTime > 0 then
        self.skeletonAnimation.Skeleton.A = self.caster.curFadeTime / self.caster.fadeTime;
    end

    --被眩晕后删除技能特效
    if self.caster and self.caster.aniState == Config.AnimationState.STUN and self.spineType == EnumConst.SpineEffectType.SKILL then
        local isSkillOut = false;
        local skillInfo = G.dataTable["t_skill"][tostring(self.skillId)]
        if skillInfo then
            isSkillOut = G.dataTable["t_skill"][tostring(self.skillId)].f_SkillOut == 1;--是否是分离技能
        end
        if math.modf(self.skillId / 10000) == tonumber(self.caster.partnerModelId) and not isSkillOut then
            self:stop()
            return
        end
    end
    self:updateFly();

    --不循环的skill和buff通过计时结束。循环的buff，由removeBuff结束，removeBuff会结束所有add的buff。这里可能有重复移除
    if not self.loop then
        self.duration = self.duration - Time.deltaTime;
        if self.duration <= 0 then
            self:stop(true);
            return ;
        end
    end
    --循环的技能，由以下代码结束
    if self.loop and self.duration < 0 then
        self.duration = self.duration + Time.deltaTime;
        if self.duration >= 0 then
            self:stop(true);
            return ;
        end
    end
    if self.skillShowType ~= 3 and self.caster and self.caster.showDead and self.spineType ~= EnumConst.SpineEffectType.BUFF and self.spineType ~= EnumConst.SpineEffectType.BULLET then
        self.caster.showDead = false
        --logMy(self.caster.isHero,self.caster.modelName,self.caster.fighterId,self.name)
        if self.caster.isHero then
            local name = self.name .. '(Clone)'
            local gameObjectTemp = GameObject.Find(name)
            local count = 0
            while gameObjectTemp and count < 10 do
                count = count + 1
                gameObjectTemp:SetActive(false)
                gameObjectTemp = nil
                gameObjectTemp = GameObject.Find(name)
            end
            self:stop()
            return
        end
    end
    self:updateFollowPosition();
    self:updateLinkEffect();
    --self:updateHookEffect();
end

function SpineEffect:updateFly()
    if not self.hook and self.speed ~= nil then
        --这是个向量
        if FightManager.gameEnd then
            self:stop();
            return ;
        end
        local rotation = 0;
        local rotation_z = 0;
        ----Y
        --local deltaY = self:getFlyDeltaY();
        --self.flyOldPosition:Add(self.speed * Time.deltaTime);
        --self.flyOldPosition.y = self.flyOldPosition.y + deltaY;
        --self.effGo.transform.position = self.flyOldPosition;-- + Vector3(0, deltaY, 0);
        --self.flyOldPosition.y = self.flyOldPosition.y - deltaY;
        local dt = Time.deltaTime
        local skillShow = G.dataTable["t_skillshow"][tostring(self.skillId)];
        local hitPos = self.suffer:getOffsetPosition(skillShow.f_HitFPosition, self.suffer.flip);
        local vecX, vecY, vecZ = Util.Lua_GetLocalPositionXYZ(self.effGo.transform, 0, 0, 0);

        local flyStartPos = Vector3(vecX, vecY, vecZ);
        local s = nil;
        local flyDir = hitPos - flyStartPos;
        if self.targetPos then
            flyDir = self.targetPos - flyStartPos;
            s = Vector3.Normalize(flyDir) * self.speed * dt;
        else
            s = Vector3(flyDir.x * (dt / self.duration), flyDir.y * (dt / self.duration), flyDir.z * (dt / self.duration));
            if self.duration <= dt then
                s = flyDir;
            end
        end
        local distance = flyDir.magnitude;
        local flySpeed = math.abs(distance / self.duration);

        local flip = true;
        if not self.flyHold then
            if s.x < 0 then
                rotation = math.atan(s.z / math.abs(s.x)) / math.pi * 180;
                rotation = -rotation;
            else
                rotation = math.atan(s.z / math.abs(s.x)) / math.pi * 180;
                flip = false;

            end
        end
        if self.skillClass then
            local position = self.skillClass.position;
            Util.Lua_SetLocalPositionXYZ(self.effGo, position.x, vecY, position.y)
            Util.Lua_SetLocalRotationXYZ(self.effGo, 40, 0, rotation)
        else
            Util.Lua_GameObjectAddPosAndSetRot(self.effGo, s.x, s.y, s.z, 40, 0, rotation);
        end
        Util.SetFlipX(self.skeletonAnimation, flip);
    end
end

function SpineEffect:getFlyDeltaY()
    local t = (self.flyTime - self.duration) / self.flyTime;
    --local d = EffectFunctions.calcYByGravity(t);
    local d = EffectFunctions.calcY(t);
    return d;

    --local deltaY = d - self.flyY;
    --self.flyY = d;
    --logMy('getFlyDeltaY', self.flyTime, self.duration, t, d, deltaY);
    --return deltaY;
end

function SpineEffect:updateFollowPosition()

    if self.follow then
        if FightManager.gameEnd then
            self:stop();
            return ;
        end
        if self.suffer and not HelperFunc.IsNull(self.suffer.skeletonAnimation) and self.suffer.skeletonAnimation.Skeleton.A == 0 and self.name ~= 'b022' then
            self.duration = 0
            return
        end

        EffectFunctions.calcFollowPositionV2(self.followInfo);
        local followPos = self.followInfo.position;
        if self.subName == "fxh611f" or self.subName == "fxh611b" then
            Util.SetFlipX(self.skeletonAnimation, self.caster.flip);
        end
        if followPos then
            Util.Lua_SetGameObjectPositionXYZ(self.effGo, followPos.x, followPos.y, followPos.z)
            if self.caster ~= nil and not HelperFunc.IsNull(self.caster.roleObj) then
                if self.caster.skeletonAnimation then
                    local transform = self.caster.skeletonAnimation.gameObject.transform;
                    if transform and self.caster.attackShowType == EnumConst.AttackShowType.SPRINT  then
                        Util.Lua_GameObjectAddPosAndSetRot(self.effGo, 0, 0, 0, transform.localEulerAngles.x, transform.localEulerAngles.y, transform.localEulerAngles.z);
                    end
                end
            end
        end
    end
end

function SpineEffect:initPosition()
    local aniTrans = not HelperFunc.IsNull(self.skeletonAnimation) and self.skeletonAnimation or self.effGo.transform:Find("Animation")
    if self.speed ~= nil then
        self.RenderQueueRate = 0
    end
    if self.follow then
        self:updateFollowPosition();
    elseif self.linkEffect then
        self:updateLinkEffect();
    elseif self.hook then
        self:updateHookEffect();
    else
        self.position = self.pos + self.rotatedOffset;
        Util.Lua_SetPositionXYZ(self.effGo.transform, self.position.x, self.position.y, self.position.z)
    end

    --子弹，弓箭等跟随的粒子特效
    self:playParticleEffect();
    Util.Lua_SetLocalPositionXYZ(aniTrans.gameObject, 0, 0, self.RenderQueueRate);
    --if self.speed ~= nil then
    --    self.flyTime = self.duration;
    --    self.flyOldPosition = self.effGo.transform.position;
    --    --self.flyY = 0;
    --end
end

function SpineEffect:initOther()

    --self.renderOrder = -100;

    local effName = self.name;
    if effName == "magician02" then
        setLayer(self.effGo.gameObject, LayerMask.NameToLayer("UI"));
    else
        setLayer(self.effGo.gameObject, LayerMask.NameToLayer("role"));
    end

    local ani = self.effGo.transform:Find("Animation");
    self.skeletonAnimation = ani.gameObject:GetComponent(TSkeletonAnimation);
    if HelperFunc.IsNull(self.skeletonAnimation) or self.skeletonAnimation.skeletonDataAsset == nil then
        logMy('SpineEffect load error, ', self.name);
        return
    end
    self.skeletonAnimation.Skeleton.A = 1;


    --add error log
    if HelperFunc.IsNull(self.skeletonAnimation) or self.skeletonAnimation.skeletonDataAsset == nil then
        logMy('SpineEffect load error, ', self.name);
    end

    self:bindLinkEffect(self.skeletonAnimation);

    if ani and ani.gameObject and self.spineType ~= EnumConst.SpineEffectType.HIT then
        Util.SetFlipX(self.skeletonAnimation, self.flip);
        self:updateRenderOrder();
    end

    if self.speed ~= nil and not self.flyHold then
        Util.Lua_SetLocalRotationXYZ(self.skeletonAnimation.transform, 0, 0, 0)
    end

    --self.transformCache = self.effGo.transform;
end

function SpineEffect:updateRenderOrder()

    local newRenderOrder = self.depth;
    if FightManager.cutInState and self.fighterId == FightManager.cutInFighterId and self.depth ~= Config.SortingDefault.FullScreen then
        newRenderOrder = self.depth + Config.SortingDefault.FullScreen;
    end

    if newRenderOrder ~= self.renderOrder and not HelperFunc.IsNull(self.skeletonAnimation) then
        Util.SetOrder(self.skeletonAnimation.gameObject, newRenderOrder);
        self.renderOrder = newRenderOrder;
    end
end

function SpineEffect:playAction(actionName)
    --logMy('SpineEffect:playAction', self.skeletonAnimation ~= nil, self.name, actionName, self.loop, self.speed);

    self.actionName = actionName;
    self.loop = self.loop or false;
    self.timeScale = self.timeScale or 1;

    if not HelperFunc.IsNull(self.skeletonAnimation) then
        local funDo = function()
            local durTime = self.skeletonAnimation.skeleton.Data:FindAnimation(actionName).Duration
            local orgFrame = durTime / (EnumConst.FIGHT_FRAME / EnumConst.THOUSANDTH)
            local timeRate = 1; -- orgFrame / (orgFrame - 1)

            --local isSkill = string.find(actionName, "skill", 1)
            --local isHit = string.find(actionName, "hit", 1)
            --if actionName == "attack" or (isSkill and not isHit) then
            --    timeRate = orgFrame / (orgFrame - 2)
            --end
            if self.speed == nil then
                --printError("id",self.skillId,"speed", self.timeScale * timeRate)
                local duration = 0;
                if actionName== "skill3"and self.subName == "fxh068f" then
                    duration = Util.PlayAction(self.skeletonAnimation, actionName, self.loop, -1, true, 1);
                else
                    duration = Util.PlayAction(self.skeletonAnimation, actionName, self.loop, -1, true, self.timeScale * timeRate);
                end

                if self.isCut == 1 and self.spineType == EnumConst.SpineEffectType.SKILL then
                    SpineEffectManager.addPlayingEffect(self.caster.fighterId, self.subName, self.effGo)
                end
                if self.duration == nil or self.duration == 0 then
                    self.duration = duration;
                end
                --log("self.duration2:"..self.duration)
            else
                Util.PlayAction(self.skeletonAnimation, actionName, self.loop, -1, true, self.timeScale * timeRate);

                if self.isCut == 1 and self.spineType == EnumConst.SpineEffectType.SKILL then
                    SpineEffectManager.addPlayingEffect(self.caster.fighterId, self.subName, self.effGo)
                end
            end
        end
        local res, str = pcall(funDo, nil)
        --if res then
        --    --logMy("检查素材",self.name)
        --    if self.speed == nil then
        --        local duration = Util.PlayAction(self.skeletonAnimation, actionName, self.loop, -1, true, self.timeScale);
        --        if self.duration == nil or self.duration == 0 then
        --            self.duration = duration;
        --        end
        --        --log("self.duration2:"..self.duration)
        --    else
        --        Util.PlayAction(self.skeletonAnimation, actionName, self.loop, -1, true, self.timeScale);
        --    end
        --end
    end

end

--function SpineEffect:playAnimation(aniName, loop, time, isEffect, timeScale)
--
--    self.actionName = aniName;
--    if self.skeletonAnimation then
--        Util.PlayAction(self.skeletonAnimation,aniName,loop,time,isEffect, timeScale);
--    end
--
--end

function SpineEffect:setTimeScale()

    --if self.name == 'fxh016f' then
    --    logMy('SpineEffect:setFlip.', flip, self.name);
    --end
    if not HelperFunc.IsNull(self.skeletonAnimation) and self.actionName then
        Util.SetActionTimeScale(self.skeletonAnimation, self.actionName, self.timeScale);
    end
end

function SpineEffect:setFlip(flip)

    --if self.name == 'fxh016f' then
    --    logMy('SpineEffect:setFlip.', flip, self.name);
    --end

    self.flip = flip;
    if not HelperFunc.IsNull(self.skeletonAnimation) then
        Util.SetFlipX(self.skeletonAnimation, flip);
    end
end

function SpineEffect:getSkeletonAnimation()
    return self.skeletonAnimation;
end

--添加跟随的粒子特效
function SpineEffect:playParticleEffect()

    --local effectFRes = 'EFF_DropParticle';
    local effectCfg = self:getParticleEffectConfig();
    --logMy('playParticleEffect effectCfg', effectCfg);

    if effectCfg then
        local offset = effectCfg.f_ParticlePosition:split(',');
        --logMy('playParticleEffect offset', offset);

        local color = effectCfg.f_ParticleColor:split(',');
        --logMy('playParticleEffect color', color);

        local param = ParticleSystemEffectParam.Get(effectCfg.f_ParticleName, self.depth, self.flip);
        param:setFollow(self.effGo.transform, { toNumber(offset[1]), tonumber(offset[2]) });  --如果有个占位符go的话，不需要等这边的effGo load完成
        --param:setColor(1, 0,0,1);
        param:setColor(toNumber(color[1]), tonumber(color[2]), tonumber(color[3]), tonumber(color[4]));
        param:setDelayEndTime(tonumber(effectCfg.f_DelayEndTime));
        param:setFighterId(self.fighterId);

        self.psEffect = ParticleSystemEffect:new(param);
        self.psEffect:start();
    end
end

function SpineEffect:getParticleEffectConfig()
    local effectTbl = G.dataTable["t_effect"];
    for k, v in pairs(effectTbl) do
        --logMy('getParticleEffectConfig', v.f_RecourseName == self.name and v.f_AnimationtName == self.actionName, v, self.name, self.actionName);
        if v.f_RecourseName == self.name and v.f_AnimationtName == self.actionName then
            return v;
        end
    end

    return nil;
end

function SpineEffect:setEffectSpeed()
    local effectTbl = G.dataTable["t_effect"];
    for k, v in pairs(effectTbl) do
        --logMy('getParticleEffectConfig', v.f_RecourseName == self.name and v.f_AnimationtName == self.actionName, v, self.name, self.actionName);
        if v.f_RecourseName == self.name and v.f_AnimationtName == self.actionName then
            return v;
        end
    end

    return nil;
end


